package com.ranyk.www.response;


import com.ranyk.www.base.BaseResult;
import com.ranyk.www.enums.ResponseEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;

import java.io.Serial;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

/**
 * CLASS_NAME: ResponseResult.java <br/>
 *
 * @author ranyk           <br/>
 * @version V1.0           <br/>
 * @decription: 后端请求响应封装公共对象  <br/>
 * @date: 2022-04-12 <br/>
 */
@Data
@SuppressWarnings("unused")
@EqualsAndHashCode(callSuper = true)
@ApiModel(description = "请求响应返回对象")
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class ResponseResult extends BaseResult {

    @Serial
    private static final long serialVersionUID = -474340318064207618L;

    /**
     * 返回响应状态
     */
    @ApiModelProperty(value = "请求响应状态,默认 true")
    private boolean status = true;

    /**
     * 构造函数,传入返回响应code、msg、status、data 构造响应对象
     *
     * @param code   响应码
     * @param msg    响应信息
     * @param status 响应状态
     * @param data   响应数据
     */
    private ResponseResult(int code, String msg, boolean status, Object data) {
        super(code, msg, data);
        this.status = status;
    }

    /**
     * builder 方法,创建一个 {@link ResponseBuilder } 的内部类对象
     *
     * @return 返回创建的 ResponseBuilder 对象实例
     */
    public static ResponseBuilder builder() {
        return new ResponseBuilder();
    }

    /**
     * 构建返回响应对象,设置响应数据,同时设置其他属性: <br/>
     * code: 200; <br/>
     * status: true; <br/>
     * msg: success; <br/>
     *
     * @param data 入参,响应数据
     * @return 返回构建后的 {@link ResponseResult} 对象
     */
    public static ResponseResult valueOfObject(Object data) {
        return builder().status(ResponseEnum.SUCCESS.getCode()).msg(ResponseEnum.SUCCESS.getMsg()).code(ResponseEnum.SUCCESS.getCode()).object(data).build();
    }

    /**
     * 构建响应对象,设置响应码
     *
     * @param code 入参,响应码
     * @return 返回构建后的 {@link ResponseResult} 对象
     */
    public static ResponseResult valueOfCode(int code) {
        return builder().status(ResponseEnum.SUCCESS.getCode()).code(code).build();
    }

    /**
     * 构建响应对象,设置响应码
     *
     * @param code 入参,响应码
     * @return 返回构建后的 {@link ResponseResult} 对象
     */
    public static ResponseResult valueOfStatus(Integer code) {
        return builder().status(code).build();
    }

    /**
     * 构建响应对象,设置响应码
     *
     * @param msg 入参,响应信息
     * @return 返回构建后的 {@link ResponseResult} 对象
     */
    public static ResponseResult valueOfMsg(String msg) {
        return builder().status(200).msg(msg).build();
    }

    /**
     * CLASS_NAME: ResponseBuilder.java <br/>
     *
     * @author ranyk           <br/>
     * @version V1.0           <br/>
     * @decription: 响应构建对象, 内部类  <br/>
     * @date: 2022-04-12 <br/>
     */
    public static class ResponseBuilder {

        /**
         * 响应状态
         */
        private boolean status;
        /**
         * 响应信息
         */
        private String msg;
        /**
         * 响应数据
         */
        private Object data;
        /**
         * 响应码
         */
        private int code;
        /**
         * 数据存放 Map 集合
         */
        private final Map<String, Object> map;

        /**
         * 构造函数,构造一个 {@link ResponseBuilder} 对象,该对象各属性值为: <br/>
         * code: 200; <br/>
         * msg: success; <br/>
         * status: true; <br/>
         * map: new HashMap<>(20); <br/>
         */
        ResponseBuilder() {
            this.code = ResponseEnum.SUCCESS.getCode();
            this.msg = ResponseEnum.SUCCESS.getMsg();
            this.status = true;
            this.map = new HashMap<>(20);
        }

        /**
         * 设置 {@link ResponseBuilder} 对象的 status 值, 值为传入的响应码是否等于 200
         *
         * @param code 入参,响应码
         * @return 返回 {@link ResponseBuilder} 对象
         */
        public ResponseBuilder status(int code) {
            this.status = (ResponseEnum.SUCCESS.getCode().equals(code));
            return this;
        }

        /**
         * 设置 {@link ResponseBuilder} 对象的 code 值
         *
         * @param code 入参,响应码
         * @return 返回 {@link ResponseBuilder} 对象
         */
        public ResponseBuilder code(int code) {
            this.code = code;
            return this;
        }

        /**
         * 设置 {@link ResponseBuilder} 对象的 msg 值
         *
         * @param msg 入参,响应信息
         * @return 返回 {@link ResponseBuilder} 对象
         */
        public ResponseBuilder msg(String msg) {
            this.msg = msg;
            return this;
        }

        /**
         * 设置 {@link ResponseBuilder} 对象的 data 值
         *
         * @param data 入参,响应数据
         * @return 返回 {@link ResponseBuilder} 对象
         */
        public ResponseBuilder object(Object data) {
            this.data = data;
            return this;
        }

        /**
         * 向 {@link ResponseBuilder} 对象的 map 中 put 值
         *
         * @param key   map 的键
         * @param value map 的值
         * @return 返回 {@link ResponseBuilder} 对象
         */
        public ResponseBuilder map(String key, Object value) {
            this.map.put(key, value);
            return this;
        }

        /**
         * 设置 {@link ResponseBuilder} 对象中 map 的值,同时将 map 赋给 data
         *
         * @param action 入参,Map&lt;String,Object&gt; 类型数据
         * @return 返回 {@link ResponseBuilder} 对象
         */
        public ResponseBuilder map(Consumer<Map<String, Object>> action) {
            action.accept(this.map);
            this.data = this.map;
            return this;
        }

        /**
         * 通过 {@link ResponseBuilder} 对象构建 {@link ResponseResult} 对象
         *
         * @return 返回构建好的 {@link ResponseResult} 对象
         */
        public ResponseResult build() {
            return this.data == null && this.map.size() > 0 ? new ResponseResult(this.code, this.msg, this.status, this.map) : new ResponseResult(this.code, this.msg, this.status, this.data);
        }

    }

}
